001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.plugin;
016    
017    import com.liferay.portal.kernel.util.GetterUtil;
018    import com.liferay.portal.kernel.util.StringBundler;
019    import com.liferay.portal.kernel.util.StringPool;
020    import com.liferay.portal.kernel.util.Validator;
021    
022    import java.io.Serializable;
023    
024    import java.util.Map;
025    import java.util.StringTokenizer;
026    import java.util.concurrent.ConcurrentHashMap;
027    
028    /**
029     * @author Jorge Ferrer
030     */
031    public class Version implements Comparable<Version>, Serializable {
032    
033            public static final String UNKNOWN = "unknown";
034    
035            public static Version getInstance(String version) {
036                    Version versionObj = _versions.get(version);
037    
038                    if (versionObj == null) {
039                            versionObj = new Version(version);
040    
041                            _versions.put(version, versionObj);
042                    }
043    
044                    return versionObj;
045            }
046    
047            public static Version incrementBugFix(Version version) {
048                    String bugFix = version.getBugFix();
049    
050                    int bugFixInt = GetterUtil.getInteger(bugFix);
051    
052                    if (bugFixInt > 0) {
053                            bugFix = String.valueOf(bugFixInt + 1);
054                    }
055    
056                    return getInstance(
057                            _toString(
058                                    version.getMajor(), version.getMinor(), bugFix,
059                                    version.getBuildNumber()));
060            }
061    
062            public static Version incrementBuildNumber(Version version) {
063                    String buildNumber = version.getBuildNumber();
064    
065                    int buildNumberInt = GetterUtil.getInteger(buildNumber);
066    
067                    if (buildNumberInt > 0) {
068                            buildNumber = String.valueOf(buildNumberInt + 1);
069                    }
070    
071                    return getInstance(
072                            _toString(
073                                    version.getMajor(), version.getMinor(), version.getBugFix(),
074                                    buildNumber));
075            }
076    
077            public static Version incrementMajor(Version version) {
078                    String major = version.getMajor();
079    
080                    int majorInt = GetterUtil.getInteger(major);
081    
082                    if (majorInt > 0) {
083                            major = String.valueOf(majorInt + 1);
084                    }
085    
086                    return getInstance(
087                            _toString(
088                                    major, version.getMinor(), version.getBugFix(),
089                                    version.getBuildNumber()));
090            }
091    
092            public static Version incrementMinor(Version version) {
093                    String minor = version.getMinor();
094    
095                    int minorInt = GetterUtil.getInteger(minor);
096    
097                    if (minorInt > 0) {
098                            minor = String.valueOf(minorInt + 1);
099                    }
100    
101                    return getInstance(
102                            _toString(
103                                    version.getMajor(), minor, version.getBugFix(),
104                                    version.getBuildNumber()));
105            }
106    
107            @Override
108            public int compareTo(Version version) {
109                    if (version == null) {
110                            return 1;
111                    }
112    
113                    // Unknown is always considered a lower version
114    
115                    if (version.toString().equals(UNKNOWN)) {
116                            return 1;
117                    }
118    
119                    if (toString().equals(UNKNOWN)) {
120                            return -1;
121                    }
122    
123                    int result = _compareAsIntegers(getMajor(), version.getMajor());
124    
125                    if (result != 0) {
126                            return result;
127                    }
128    
129                    result = _compareAsIntegers(getMinor(), version.getMinor());
130    
131                    if (result != 0) {
132                            return result;
133                    }
134    
135                    result = _compareAsIntegers(getBugFix(), version.getBugFix());
136    
137                    if (result != 0) {
138                            return result;
139                    }
140    
141                    return _compareAsIntegers(getBuildNumber(), version.getBuildNumber());
142            }
143    
144            @Override
145            public boolean equals(Object obj) {
146                    if (this == obj) {
147                            return true;
148                    }
149    
150                    if (!(obj instanceof Version)) {
151                            return false;
152                    }
153    
154                    Version version = (Version)obj;
155    
156                    String versionString1 = toString();
157                    String versionString2 = version.toString();
158    
159                    if (versionString1.equals(UNKNOWN) || versionString2.equals(UNKNOWN)) {
160                            return false;
161                    }
162    
163                    return versionString1.equals(versionString2);
164            }
165    
166            public String getBugFix() {
167                    if (_bugFix == null) {
168                            return "0";
169                    }
170    
171                    return _bugFix;
172            }
173    
174            public String getBuildNumber() {
175                    return _buildNumber;
176            }
177    
178            public String getMajor() {
179                    if (_major == null) {
180                            return "0";
181                    }
182    
183                    return _major;
184            }
185    
186            public String getMinor() {
187                    if (_minor == null) {
188                            return "0";
189                    }
190    
191                    return _minor;
192            }
193    
194            @Override
195            public int hashCode() {
196                    return toString().hashCode();
197            }
198    
199            public boolean includes(Version version) {
200                    if (equals(version)) {
201                            return true;
202                    }
203    
204                    if (getMajor().equals(StringPool.STAR)) {
205                            return true;
206                    }
207    
208                    if (getMajor().equals(version.getMajor())) {
209                            if (getMinor().equals(StringPool.STAR)) {
210                                    return true;
211                            }
212    
213                            if (getMinor().equals(version.getMinor())) {
214                                    if (getBugFix().equals(StringPool.STAR)) {
215                                            return true;
216                                    }
217    
218                                    if (getBugFix().equals(version.getBugFix())) {
219                                            if (getBuildNumber().equals(StringPool.STAR) ||
220                                                    getBuildNumber().equals(version.getBuildNumber())) {
221    
222                                                    return true;
223                                            }
224                                            else if (_contains(
225                                                                    getBuildNumber(), version.getBuildNumber())) {
226    
227                                                    return true;
228                                            }
229                                    }
230                                    else if (_contains(getBugFix(), version.getBugFix())) {
231                                            return true;
232                                    }
233                            }
234                            else if (_contains(getMinor(), version.getMinor())) {
235                                    return true;
236                            }
237                    }
238                    else if (_contains(getMajor(), version.getMajor())) {
239                            return true;
240                    }
241    
242                    return false;
243            }
244    
245            public boolean isLaterVersionThan(String version) {
246                    if (compareTo(getInstance(version)) > 0) {
247                            return true;
248                    }
249                    else {
250                            return false;
251                    }
252            }
253    
254            public boolean isPreviousVersionThan(String version) {
255                    if (compareTo(getInstance(version)) < 0) {
256                            return true;
257                    }
258                    else {
259                            return false;
260                    }
261            }
262    
263            public boolean isSameVersionAs(String version) {
264                    if (compareTo(getInstance(version)) == 0) {
265                            return true;
266                    }
267                    else {
268                            return false;
269                    }
270            }
271    
272            @Override
273            public String toString() {
274                    return _toString(_major, _minor, _bugFix, _buildNumber);
275            }
276    
277            protected Version(String version) {
278                    StringTokenizer st = new StringTokenizer(version, _SEPARATOR);
279    
280                    _major = st.nextToken();
281    
282                    if (st.hasMoreTokens()) {
283                            _minor = st.nextToken();
284                    }
285    
286                    if (st.hasMoreTokens()) {
287                            _bugFix = st.nextToken();
288                    }
289    
290                    if (st.hasMoreTokens()) {
291                            _buildNumber = st.nextToken();
292                    }
293                    else {
294                            _buildNumber = null;
295                    }
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 = GetterUtil.getInteger(
307                                            containerNumberString);
308                                    int number = GetterUtil.getInteger(numberString);
309    
310                                    return containerNumber <= number;
311                            }
312                            catch (NumberFormatException nfe) {
313                                    return false;
314                            }
315                    }
316    
317                    return false;
318            }
319    
320            private static String _toString(
321                    String major, String minor, String bugFix, String buildNumber) {
322    
323                    StringBundler sb = new StringBundler(7);
324    
325                    sb.append(major);
326    
327                    if (Validator.isNotNull(minor)) {
328                            sb.append(_SEPARATOR);
329                            sb.append(minor);
330    
331                            if (Validator.isNotNull(bugFix)) {
332                                    sb.append(_SEPARATOR);
333                                    sb.append(bugFix);
334    
335                                    if (Validator.isNotNull(buildNumber)) {
336                                            sb.append(_SEPARATOR);
337                                            sb.append(buildNumber);
338                                    }
339                            }
340                    }
341    
342                    return sb.toString();
343            }
344    
345            private int _compareAsIntegers(String first, String second) {
346                    int firstInteger = GetterUtil.getInteger(first);
347                    int secondInteger = GetterUtil.getInteger(second);
348    
349                    if (firstInteger < secondInteger) {
350                            return -1;
351                    }
352                    else if (firstInteger == secondInteger) {
353                            return 0;
354                    }
355                    else {
356                            return 1;
357                    }
358            }
359    
360            private static final String _SEPARATOR = StringPool.PERIOD;
361    
362            private static final Map<String, Version> _versions =
363                    new ConcurrentHashMap<>();
364    
365            private String _bugFix;
366            private final String _buildNumber;
367            private String _major;
368            private String _minor;
369    
370    }