001    package org.mycore.frontend.indexbrowser.lucene;
002    
003    import java.util.Hashtable;
004    import java.util.List;
005    import java.util.concurrent.locks.ReentrantReadWriteLock;
006    
007    import org.apache.log4j.Logger;
008    import org.mycore.common.MCRCache;
009    import org.mycore.common.MCRException;
010    
011    /**
012     * Caches index browser entries in a hash table. Each object type 
013     * gets an entry in the table. The value of an entry is a MCRCache.
014     * This cache again creates new entries for different search and modes.
015     * So the cache key is: object index # search # mode
016     *
017     * @author Matthias Eichner
018     */
019    public class MCRIndexBrowserCache {
020        protected static Logger LOGGER = Logger.getLogger(MCRIndexBrowserCache.class);
021    
022        private static Hashtable<String, MCRCache> TYPE_CACHE_TABLE = new Hashtable<String, MCRCache>();
023        private static ReentrantReadWriteLock TYPE_CACHE_TABLE_LOCK = new ReentrantReadWriteLock();
024    
025        /**
026         * Add a new list of index browser entries to the cache.
027         * @param listToCache a list to cache
028         */
029        public static void addToCache(MCRIndexBrowserIncomingData browseData, String index, List<MCRIndexBrowserEntry> listToCache) {
030            if(browseData == null || index == null || listToCache == null)
031                return;
032    
033            // adds a new mcr cache to the hash table
034            MCRCache mcrCache = null;
035            if(!isInHashtable(index)) {
036                mcrCache = addIndexCacheToHashtable(index);
037            } else {
038                mcrCache = getIndexCache(index);
039            }
040            // add the index browser entry list to the mcr cache
041            String cacheKey = getCacheKey(index, browseData);
042            mcrCache.put(cacheKey, listToCache);
043        }
044    
045        /**
046         * Adds a new MCRCache to the hash table.
047         * @param index the key of the entry.
048         */
049        protected static MCRCache addIndexCacheToHashtable(String index) {
050            if (index == null)
051                throw new MCRException("Could not determine index: " + index);
052            MCRCache cache = null;
053            try {
054                TYPE_CACHE_TABLE_LOCK.writeLock().lock();
055                if (!TYPE_CACHE_TABLE.containsKey(index))
056                    TYPE_CACHE_TABLE.put(index, cache = new MCRCache(1000, "IndexBrowser,objectType=" + index.replace(",", "_")));
057            } finally {
058                TYPE_CACHE_TABLE_LOCK.writeLock().unlock();
059            }
060            return cache;
061        }
062    
063        /**
064         * Deletes a whole MCRCache from the hash table.
065         * @param objectType the object type which has to be removed
066         */
067        public static void deleteIndexCacheFromHashtable(String objectType) {
068            if (objectType == null)
069                return;
070            TYPE_CACHE_TABLE_LOCK.writeLock().lock();
071            TYPE_CACHE_TABLE.remove(objectType);
072            TYPE_CACHE_TABLE_LOCK.writeLock().unlock();
073        }
074        
075        /**
076         * Returns the cached index browser list.
077         * @return the cached list.
078         */
079            public static List<MCRIndexBrowserEntry> getFromCache(String index, MCRIndexBrowserIncomingData browseData) {
080            // if the list is not cached, return null
081            if(!isCached(index, browseData))
082                return null;
083    
084            String cacheKey = getCacheKey(index, browseData);
085            // get the mcr cache from the hash table
086            MCRCache mcrCache = getIndexCache(index);
087            // get the cached list from the mcr cache
088            @SuppressWarnings("unchecked")
089            List<MCRIndexBrowserEntry> cachedList = ((List<MCRIndexBrowserEntry>)mcrCache.get(cacheKey));
090            // return the list
091            return cachedList;
092        }
093    
094        /**
095         * Returns the MCRCache from the hash table by the given index name.
096         * @param index the index name of the specific index browser
097         * @return a MCRCache from the hash table
098         */
099        protected static MCRCache getIndexCache(String index) {
100            try {
101                TYPE_CACHE_TABLE_LOCK.readLock().lock();
102                return TYPE_CACHE_TABLE.get(index);
103            } finally {
104                TYPE_CACHE_TABLE_LOCK.readLock().unlock();
105            }
106        }
107    
108        /**
109         * Returns the cache key from the incoming browser data.
110         * @return the cache key in the form of index # search # mode
111         */
112        protected static String getCacheKey(String index, MCRIndexBrowserIncomingData browseData) {
113            String key = "";
114            if(index != null)
115                key += index;
116            key += "#";
117            if(browseData.getSearch() != null)
118                key += browseData.getSearch();
119            key += "#";
120            if(browseData.getMode() != null)
121                key += browseData.getMode();
122            return key;
123        }
124    
125        /**
126         * Checks if a hash table entry with the specified index
127         * exists. If true, the method checks if the specified key
128         * exists in the MCRCache.
129         * @return true if an entry in the hash table and in the MCRCache exists,
130         * otherwise false
131         */
132        public static boolean isCached(String index, MCRIndexBrowserIncomingData browseData) {
133            String cacheKey = getCacheKey(index, browseData);
134            try {
135                TYPE_CACHE_TABLE_LOCK.readLock().lock();
136                MCRCache mcrCache = TYPE_CACHE_TABLE.get(index);
137                if (mcrCache != null && mcrCache.get(cacheKey) != null)
138                    return true;
139                return false;
140            } finally {
141                TYPE_CACHE_TABLE_LOCK.readLock().unlock();
142            }
143        }
144    
145        /**
146         * Checks if the entry exists in the hash table.
147         * @param key the key which will be checked
148         * @return true if the entry was found, otherwise false
149         */
150        public static boolean isInHashtable(String key) {
151            try {
152                TYPE_CACHE_TABLE_LOCK.readLock().lock();
153                return TYPE_CACHE_TABLE.containsKey(key);
154            } finally {
155                TYPE_CACHE_TABLE_LOCK.readLock().unlock();
156            }
157        }
158    }