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