View Javadoc

1   package com.atlassian.seraph.util;
2   
3   import edu.emory.mathcs.backport.java.util.concurrent.locks.ReadWriteLock;
4   import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantReadWriteLock;
5   
6   import java.util.Collection;
7   import java.util.Iterator;
8   import java.util.Map;
9   
10  /**
11   * Caches the results of the {@link PathMapper}
12   */
13  public class CachedPathMapper implements IPathMapper
14  {
15      private final ReadWriteLock lock = new ReentrantReadWriteLock();
16      private final PathMapper delegate = new PathMapper();
17      private final Map cacheMap;
18      private final Map cacheAllMap;
19  
20      /**
21       * Creates a CachedPathMapper object that will use cacheMap to cache the results of the {@link #get(String)} calls and cacheAllMap to cache the
22       * results of the {@link #getAll(String)} class.
23       * <p>
24       * Use the passed in maps for caches. The maps must be thread-safe as far as {@link Map#get(Object)} calls are concerned as gets may happen
25       * concurrently. An access ordered map should be wrapped in a synchronizedMap wrapper.
26       * 
27       * @param cacheMap
28       *            for caching results of {@link #get(String)} calls
29       * @param cacheAllMap
30       *            for caching results of {@link #getAll(String)} calls
31       */
32      public CachedPathMapper(final Map cacheMap, final Map cacheAllMap)
33      {
34          this.cacheMap = cacheMap;
35          this.cacheAllMap = cacheAllMap;
36      }
37  
38      public String get(final String path)
39      {
40          lock.readLock().lock();
41          try
42          {
43              // Check the cache
44              final String result = (String) cacheMap.get(path);
45              if (result != null)
46              {
47                  return result;
48              }
49          }
50          finally
51          {
52              lock.readLock().unlock();
53          }
54          return getWithLock(path);
55      }
56  
57      private String getWithLock(final String path)
58      {
59          final String result = delegate.get(path);
60          // Get the result from PathMapper
61          // Cache the result
62          lock.writeLock().lock();
63          try
64          {
65              cacheMap.put(path, result);
66              return result;
67          }
68          finally
69          {
70              lock.writeLock().unlock();
71          }
72      }
73  
74      public Collection getAll(final String path)
75      {
76          lock.readLock().lock();
77          try
78          {
79              final Collection result = (Collection) cacheAllMap.get(path);
80              // Check the cache
81              if (result != null)
82              {
83                  // The result for this key is cached, return the value
84                  return result;
85              }
86          }
87          finally
88          {
89              lock.readLock().unlock();
90          }
91          return getAllWithLock(path);
92      }
93  
94      private Collection getAllWithLock(final String path)
95      {
96          // Get the result from delegate PathMapper
97          final Collection result = delegate.getAll(path);
98          // Cache the result
99          lock.writeLock().lock();
100         try
101         {
102             cacheAllMap.put(path, result);
103             return result;
104         }
105         finally
106         {
107             lock.writeLock().unlock();
108         }
109     }
110 
111     public void set(final Map/* <String, String> */patterns)
112     {
113         lock.writeLock().lock();
114         try
115         {
116             for (final Iterator/* <Entry<String, String>> */it = patterns.entrySet().iterator(); it.hasNext();)
117             {
118                 final Map.Entry/* <String, String> */entry = (Map.Entry) it.next();
119                 put((String) entry.getKey(), (String) entry.getValue());
120             }
121         }
122         finally
123         {
124             lock.writeLock().unlock();
125         }
126     }
127 
128     public void put(final String key, final String pattern)
129     {
130         lock.writeLock().lock();
131         try
132         {
133             // Let the delegate mapper update the patterns
134             delegate.put(key, pattern);
135             cacheMap.remove(key);
136             cacheAllMap.remove(key);
137         }
138         finally
139         {
140             lock.writeLock().unlock();
141         }
142     }
143 
144     public String toString()
145     {
146         return delegate.toString();
147     }
148 }