View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.core.api.util;
17  
18  
19  import org.apache.commons.lang.StringUtils;
20  
21  import java.util.regex.Matcher;
22  import java.util.regex.Pattern;
23  
24  /**
25   *
26   * Helper class for comparing version strings
27   *
28   * @author Kuali Rice Team (rice.collab@kuali.org)
29   *
30   */
31  public class VersionHelper {
32  
33      // This pattern matches any non-digit string containing a version number of the form A.B.C.D followed by any non-digit string
34      private static final Pattern extractVersion = Pattern.compile("(\\D*)((\\d*\\.?)+)(\\D*)");
35  
36      // Pattern used for splitting version number for comparison
37      private static final Pattern splitVersion = Pattern.compile("\\.");
38  
39      /**
40       * returns -1 if versionOne is less than versionTwo, 0 if the versions are equal, and 1 if versionOne is more recent than versionTwo
41       *
42       * @param versionOne string representation of a version
43       * @param versionTwo string representation of a version
44       * @return int
45       */
46  
47      public static int compareVersion(String versionOne, String versionTwo) {
48          try {
49              return compareVersionInt(versionOne, versionTwo);
50          } catch (IllegalArgumentException iae) {
51                 return -1;
52          }
53  
54      }
55  
56      private static int compareVersionInt(String versionOne, String versionTwo) throws IllegalArgumentException {
57  
58  
59          if (StringUtils.isBlank(versionOne) || StringUtils.isBlank(versionTwo)) {
60              throw new IllegalArgumentException("Invalid argument");
61          }
62  
63          Matcher m1 = extractVersion.matcher(versionOne);
64          Matcher m2 = extractVersion.matcher(versionTwo);
65  
66          if (!m1.matches() || !m2.matches()) {
67              throw new IllegalArgumentException("Unable to extract version number from string using regex");
68          }
69  
70          //uses the matches generated by the extractVersion pattern to pull the version out of a string
71          //  i.e. "2.1.3-SNAPSHOT" after sanitization is "2.1.3"
72  
73          String sanitizedVOne = versionOne.substring(m1.start(2), m1.end(2));
74          String sanitizedVTwo = versionTwo.substring(m2.start(2), m2.end(2));
75  
76          //uses the splitPattern to break a string into an array of numeric strings
77          // i.e. "2.1.3" becomes {"2", "1", "3"}
78  
79          String[] oneDigits = splitVersion.split(sanitizedVOne);
80          String[] twoDigits = splitVersion.split(sanitizedVTwo);
81  
82          // if there are unequal arrays, iterate over arrays up to the length of the shorter array
83          // have to be able to deal with the case "2.1" compared to "2.1.3"
84          int length=0;
85          if (oneDigits.length<twoDigits.length) {
86              length=oneDigits.length;
87          } else {
88              length=twoDigits.length;
89          }
90  
91          for(int i=0; i<length; i++) {
92              Integer intOne = Integer.valueOf(oneDigits[i]);
93              Integer intTwo = Integer.valueOf(twoDigits[i]);
94              Integer compare = intOne.compareTo(intTwo);
95              if (compare < 0) {
96                  return -1;
97              }
98              else if (compare > 0) {
99                  return 1;
100             }
101         }
102         if (oneDigits.length<twoDigits.length) {
103             return -1;
104         }
105         if (oneDigits.length==twoDigits.length) {
106             return 0;
107         }
108         return 1;
109 
110     }
111 
112 
113 }
114 
115