• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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