View Javadoc
1   /*******************************************************************************
2    * Copyright 2012 Internet2
3    * 
4    * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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  /*
17   * @author mchyzer
18   * $Id: GrouperVersion.java,v 1.9 2009-11-18 17:03:50 mchyzer Exp $
19   */
20  package edu.internet2.middleware.grouperInstaller;
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.regex.Matcher;
25  import java.util.regex.Pattern;
26  
27  import edu.internet2.middleware.grouperInstaller.util.GrouperInstallerUtils;
28  
29  
30  
31  /**
32   * keep track of which version grouper is.  Update this file (the GROUPER_VERSION constant) before each
33   * non-release-candidate release
34   */
35  public class GiGrouperVersion {
36    
37    /**
38     * return the parsed and tostring version of this version string (consistent), 
39     * or null if nothing passed in
40     * @param versionString
41     * @return the version string
42     */
43    public static String stringValueOrNull(String versionString) {
44      if (GrouperInstallerUtils.isBlank(versionString)) {
45        return null;
46      }
47      return valueOfIgnoreCase(versionString, true).toString();
48    }
49    
50    /**
51     * @see Object#equals(Object)
52     */
53    @Override
54    public boolean equals(Object obj) {
55      if (!(obj instanceof GiGrouperVersion)) {
56        return false;
57      }
58      GiGrouperVersion../edu/internet2/middleware/grouperInstaller/GiGrouperVersion.html#GiGrouperVersion">GiGrouperVersion other = (GiGrouperVersion)obj;
59      if (this.build != other.build) {
60        return false;
61      }
62      if (this.major != other.major) {
63        return false;
64      }
65      if (this.minor != other.minor) {
66        return false;
67      }
68      if (!GrouperInstallerUtils.equals(this.rc, other.rc)) {
69        return false;
70      }
71      return true;
72    }
73  
74    
75    
76    /**
77     * @see java.lang.Object#hashCode()
78     */
79    @Override
80    public int hashCode() {
81      
82      return ("" + this.major + "" + this.minor + "" + this.build + "" + this.rc).hashCode();
83      
84    }
85  
86  
87    /**
88     * 
89     * @see java.lang.Object#toString()
90     */
91    @Override
92    public String toString() {
93      String result = this.major + "." + this.minor + "." + this.build;
94      if (this.rc != null) {
95        result+= "rc" + this.rc;
96      }
97      return result;
98    }
99    
100   /**
101    * se we dont have to keep constructing this
102    */
103   private static GiGrouperVersion currentVersion = null;
104   
105   /**
106    * current grouper version
107    * @return current grouper version
108    */
109   public static GiGrouperVersion currentVersion() {
110     if (currentVersion == null) {
111       currentVersion = valueOfIgnoreCase(GrouperInstallerUtils.grouperInstallerVersion());
112     }
113     return currentVersion;
114   }
115   
116   
117   /** major number */
118   private int major;
119   
120   /** minor number */
121   private int minor;
122 
123   /** build number */
124   private int build;
125   
126   /** rc number (release cnadidate) */
127   private Integer rc;
128 
129   /** keep a map of max size 1000 */
130   private static Map<String, GiGrouperVersion> versionCache = new HashMap<String, GiGrouperVersion>();
131 
132   /**
133    * convert string to version like an enum would
134    * 
135    * @param string cannot be blank
136    * @return the enum or null or exception if not found
137    */
138   public static GiGrouperVersion valueOfIgnoreCase(String string) {
139     return valueOfIgnoreCase(string, true);
140   }
141 
142   /**
143    * convert string to version like an enum would
144    * 
145    * @param string
146    * @param exceptionOnNull will not allow null or blank entries
147    * @return the enum or null or exception if not found
148    */
149   public static GiGrouperVersion valueOfIgnoreCase(String string, boolean exceptionOnNull) {
150 
151     if (GrouperInstallerUtils.isBlank(string)) {
152       if (exceptionOnNull) {
153         throw new RuntimeException("Not expecting a blank string for version");
154       }
155       return null;
156     }
157     
158     //see if in cache
159     GiGrouperVersion grouperVersion = versionCache.get(string);
160     if (grouperVersion != null) {
161       return grouperVersion;
162     }
163     
164     grouperVersion = new GiGrouperVersion(string);
165     
166     //dont cause a memory leak
167     if (versionCache.size() < 1000) {
168       versionCache.put(string, grouperVersion);
169     }
170     return grouperVersion;
171   }
172   
173   /**
174    * private constructor
175    * @param versionString
176    */
177   public GiGrouperVersion(String versionString) {
178     Matcher grouperMatcher = shortPattern.matcher(versionString);
179     
180     // 1.2
181     if (!grouperMatcher.matches()) {
182     
183       grouperMatcher = pattern.matcher(versionString);
184       
185       // 1.2.3
186       if (!grouperMatcher.matches()) {
187         
188 
189         grouperMatcher = rcPattern.matcher(versionString);
190         
191         // 1.2.3rc4
192         if (!grouperMatcher.matches()) {
193         
194         
195           throw new RuntimeException("Invalid version: " + versionString
196               + ", expecting something like: 1.1 or 1.2.3 or 1.2.3rc4");
197         }
198         this.rc = GrouperInstallerUtils.intValue(grouperMatcher.group(4));
199       }
200       this.build = GrouperInstallerUtils.intValue(grouperMatcher.group(3));
201 
202     }
203     //get the grouper versions
204     this.major = GrouperInstallerUtils.intValue(grouperMatcher.group(1));
205     this.minor = GrouperInstallerUtils.intValue(grouperMatcher.group(2));
206 
207   }
208   
209   /**
210    * see if the grouper version is greater than or equal to a certain version
211    * @param version
212    * @return true if the grouper version is greater than or equal to a certain version
213    */
214   public static boolean grouperVersionGreaterOrEqual(String version) {
215     return _grouperVersionGreaterOrEqualHelper(currentVersion().toString(), version);
216   }
217   
218   /**
219    * see if the grouper version is greater than or equal to a certain version
220    * @param version
221    * @return true if the grouper version is greater than or equal to a certain version
222    */
223   public boolean greaterOrEqualToArg(String version) {
224     return this.thisGreaterThanArgument(new GiGrouperVersion(version), true);
225   }
226   
227   /**
228    * see if this version is less than the argument one
229    * @param other
230    * @param orEqual 
231    * @return true if less than, false if equal or greater
232    */
233   public boolean lessThanArg(GiGrouperVersion other, boolean orEqual) {
234     //switch these around.  if a < b, then b > a
235     return other.thisGreaterThanArgument(this, orEqual);
236   }
237 
238   /**
239    * see if this version is less than the argument one, only considering major and minor version
240    * @param other
241    * @param orEqual 
242    * @return true if less than, false if equal or greater
243    */
244   public boolean lessThanMajorMinorArg(GiGrouperVersion other, boolean orEqual) {
245     
246     GiGrouperVersion thisMajorMinor = valueOfIgnoreCase(this.major + "." + this.minor + ".0");
247     GiGrouperVersion otherMajorMinor = valueOfIgnoreCase(other.major + "." + other.minor + ".0");
248     
249     return thisMajorMinor.lessThanArg(otherMajorMinor, orEqual);
250     
251   }
252 
253   /**
254    * see if this version is less than the argument one
255    * @param other
256    * @return true if less than, false if equal or greater
257    */
258   public boolean lessThanArg(GiGrouperVersion other) {
259     return this.lessThanArg(other, false);
260   }
261   
262   /**
263    * see if the grouper version is greater than or equal to a certain version
264    * @param version
265    * @return true if the grouper version is greater than or equal to a certain version
266    */
267   public boolean greaterOrEqualToArg(GiGrouperVersion version) {
268     return this.thisGreaterThanArgument(version, true);
269   }
270   
271   /**
272    * <pre>
273    * start of string, optional v or V, first digit, period or underscore, second digit, period or underscore, third digit, end of string
274    * parens are for capturing
275    * ^(\\d+)\\.(\\d+)\\.(\\d+)$
276    * </pre>
277    */
278   private static Pattern pattern = Pattern.compile("^[vV]?(\\d+)[\\._](\\d+)[\\._](\\d+)$");
279   
280   /**
281    * <pre>
282    * start of string, optional v or V, first digit, period or underscore, second digit, period or underscore, third digit, end of string
283    * parens are for capturing
284    * ^(\\d+)\\.(\\d+)$
285    * </pre>
286    */
287   private static Pattern shortPattern = Pattern.compile("^[vV]?(\\d+)[\\._](\\d+)$");
288   
289   /**
290    * <pre>
291    * start of string, optional v or V, first digit, period or underscope, second digit, period or underscore, third digit, 
292    * period, rc, 4th digit, end of string
293    * parens are for capturing
294    * ^(\\d+)\\.(\\d+)\\.(\\d+)$
295    * </pre>
296    */
297   private static Pattern rcPattern = Pattern.compile("^[vV]?(\\d+)[\\._](\\d+)[\\._](\\d+)\\-?rc(\\d+)$");
298   
299   /**
300    * helper method for unit testing
301    * @param grouperVersion
302    * @param anotherVersion
303    * @return true if grouper is greater
304    */
305   public static boolean _grouperVersionGreaterOrEqualHelper(String grouperVersion, String anotherVersion) {
306     GiGrouperVersioner/GiGrouperVersion.html#GiGrouperVersion">GiGrouperVersion grouper = new GiGrouperVersion(grouperVersion);
307     GiGrouperVersioner/GiGrouperVersion.html#GiGrouperVersion">GiGrouperVersion another = new GiGrouperVersion(anotherVersion);
308     //for grouper version to be greater or equal
309     return grouper.thisGreaterThanArgument(another, true);
310   }
311 
312   /**
313    * see if this version is greater than or equal the argument
314    * @param anotherVersion
315    * @param orEqual if true then count equals as a true
316    * @return true if this is less
317    */
318   private boolean thisGreaterThanArgument(GiGrouperVersion anotherVersion, boolean orEqual) {
319     //compare, first with major, minor, then build
320     if (this.major > anotherVersion.major) {
321       return true;
322     } else if (this.major < anotherVersion.major) {
323       return false;
324     }
325     if (this.minor > anotherVersion.minor) {
326       return true;
327     } else if (this.minor < anotherVersion.minor) {
328       return false;
329     }
330     //note its greater or equal
331     if (this.build > anotherVersion.build) {
332       return true;
333     } else if (this.build < anotherVersion.build) {
334       return false;
335     }
336     if (GrouperInstallerUtils.equals(this.rc, anotherVersion.rc)) {
337       return orEqual;
338     }
339     //not having a release candidate version is higher than having one
340     if (this.rc == null) {
341       return true;
342     }
343     if (anotherVersion.rc == null) {
344       return false;
345     }
346     return this.rc > anotherVersion.rc;
347   }
348 }