1 package org.unicode.cldr.util; 2 3 import com.google.common.cache.Cache; 4 import com.google.common.cache.CacheBuilder; 5 import com.google.common.cache.CacheStats; 6 import java.util.concurrent.Callable; 7 import java.util.concurrent.ExecutionException; 8 import java.util.regex.Pattern; 9 10 /** 11 * Simple class for caching Patterns, possibly avoiding the cost of compilation if they are in the 12 * cache. 13 * 14 * @author ribnitz 15 */ 16 public class PatternCache { 17 private static final int INITIAL_CAPACITY = 30; 18 private static final int MAX_CAPACITY = 1000; 19 20 /** 21 * Variable to control whether patterns are cached (true); or whether they are created all the 22 * time 23 */ 24 private static final boolean USE_CACHE = true; 25 26 /** Variable that controls whether statistics are recorded for the caching. */ 27 private static final boolean RECORD_STATISTICS = false; 28 29 /** The cache object */ 30 private static final Cache<String, Pattern> cache; 31 32 /* 33 * A static initialization block is used to be able to cleanly handle the three different cases: 34 * 35 * 1) no caching 36 * 2) caching without statistics collection 37 * 3) caching with statistics collection 38 */ 39 static { 40 if (USE_CACHE) { 41 if (RECORD_STATISTICS) { 42 cache = 43 CacheBuilder.newBuilder() 44 .initialCapacity(INITIAL_CAPACITY) 45 .maximumSize(MAX_CAPACITY) 46 .recordStats() 47 .build(); 48 } else { 49 cache = 50 CacheBuilder.newBuilder() 51 .initialCapacity(INITIAL_CAPACITY) 52 .maximumSize(MAX_CAPACITY) 53 .build(); 54 } 55 } else { 56 cache = null; 57 } 58 } 59 60 /** 61 * Obtain a compiled Pattern from the String given; results of the lookup are cached, a cached 62 * result will be returned if possible. 63 * 64 * @param patternStr the string to use for compilation 65 * @throws IllegalArgumentException The string provided was null or empty, or there was a 66 * problem compiling the Pattern from the String 67 */ get(final String patternStr)68 public static Pattern get(final String patternStr) { 69 // Pre-conditions: non-null, non-empty string 70 if (patternStr == null) { 71 throw new IllegalArgumentException("Please call with non-null argument"); 72 } 73 if (patternStr.isEmpty()) { 74 throw new IllegalArgumentException("Please call with non-empty argument"); 75 } 76 // If patterns are not cached, simply return a new compiled Pattern 77 if (!USE_CACHE) { 78 return Pattern.compile(patternStr); 79 } 80 Pattern result = null; 81 try { 82 result = 83 cache.get( 84 patternStr, 85 new Callable<Pattern>() { 86 87 @Override 88 public Pattern call() throws Exception { 89 return Pattern.compile(patternStr); 90 } 91 }); 92 } catch (ExecutionException e) { 93 // realistically, this is a PatternSyntaxException 94 throw new IllegalArgumentException( 95 "The supplied pattern is not valid: " + patternStr, e); 96 } 97 return result; 98 } 99 100 /** 101 * Return true if the collection of statistics is enabled 102 * 103 * @return 104 */ isRecordStatistics()105 public static boolean isRecordStatistics() { 106 return RECORD_STATISTICS; 107 } 108 109 /** 110 * Return true if caching is enabled; in the case it isn't this class acts like a Factory for 111 * compiled Patterns 112 * 113 * @return 114 */ isCachingEnabled()115 public static boolean isCachingEnabled() { 116 return USE_CACHE; 117 } 118 119 /** 120 * Get Statistics for the Caching operation 121 * 122 * @return 123 */ getStatistics()124 public static CacheStats getStatistics() { 125 return cache.stats(); 126 } 127 } 128