001    /*
002    // $Id: //open/mondrian/src/main/mondrian/rolap/SmartMemberListCache.java#6 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 2004-2005 TONBELLER AG
007    // All Rights Reserved.
008    // You must accept the terms of that agreement to use this software.
009    */
010    package mondrian.rolap;
011    
012    import mondrian.rolap.cache.SmartCache;
013    import mondrian.rolap.cache.SoftSmartCache;
014    import mondrian.rolap.sql.SqlConstraint;
015    
016    /**
017     * Uses a {@link mondrian.rolap.cache.SmartCache} to store lists of members,
018     * where the key depends on a {@link mondrian.rolap.sql.SqlConstraint}.
019     * <p>
020     * Example 1
021     * <pre>
022     *   select ...
023     *   [Customer].[Name].members on rows
024     *   ...
025     * </pre>
026     * Example 2
027     * <pre>
028     *   select ...
029     *   NON EMPTY [Customer].[Name].members on rows
030     *   ...
031     *   WHERE ([Store#14], [Product].[Product#1])
032     * </pre>
033     *
034     * The first set, <em>all</em> customers are computed, in the second only those, who
035     * have bought Product#1 in Store#14. We want to put both results into the cache. Then the
036     * key for the cache entry is the Level that the members belong to <em>plus</em> the
037     * costraint that restricted the amount of members fetched. For Level.Members the key
038     * consists of the Level and the cacheKey of the {@link mondrian.rolap.sql.SqlConstraint}
039     *
040     * @see mondrian.rolap.sql.SqlConstraint#getCacheKey
041     *
042     * @author av
043     * @since Nov 21, 2005
044     * @version $Id: //open/mondrian/src/main/mondrian/rolap/SmartMemberListCache.java#6 $
045     */
046    public class SmartMemberListCache <K, V> {
047        SmartCache<Key2<K, Object>, V> cache;
048    
049        /**
050         * a HashMap key that consists of two components.
051         */
052        static class Key2 <T1, T2> {
053            T1 o1;
054            T2 o2;
055    
056            public Key2(T1 o1, T2 o2) {
057                this.o1 = o1;
058                this.o2 = o2;
059            }
060    
061            public boolean equals(Object obj) {
062                if (!(obj instanceof Key2)) {
063                    return false;
064                }
065                Key2 that = (Key2) obj;
066                return equals(this.o1, that.o1) && equals(this.o2, that.o2);
067            }
068    
069            private boolean equals(Object o1, Object o2) {
070                return o1 == null ? o2 == null : o1.equals(o2);
071            }
072    
073            public int hashCode() {
074                int c = 1;
075                if (o1 != null) {
076                    c = o1.hashCode();
077                }
078                if (o2 != null) {
079                    c = 31 * c + o2.hashCode();
080                }
081                return c;
082            }
083    
084            public String toString() {
085                return "key(" + o1 + "," + o2 + ")";
086            }
087        }
088    
089        public SmartMemberListCache() {
090            cache = new SoftSmartCache<Key2<K, Object>, V>();
091        }
092    
093        public Object put(K key, SqlConstraint constraint, V value) {
094            Object cacheKey = constraint.getCacheKey();
095            if (cacheKey == null) {
096                return null;
097            }
098            Key2<K, Object> key2 = new Key2<K, Object>(key, cacheKey);
099            return cache.put(key2, value);
100        }
101    
102        public V get(K key, SqlConstraint constraint) {
103            Key2<K, Object> key2 = new Key2<K, Object>(key, constraint.getCacheKey());
104            return cache.get(key2);
105        }
106    
107        public void clear() {
108            cache.clear();
109        }
110    
111        SmartCache<Key2<K, Object>, V> getCache() {
112            return cache;
113        }
114    
115        void setCache(SmartCache<Key2<K, Object>, V> cache) {
116            this.cache = cache;
117        }
118    }
119    
120    // End SmartMemberListCache.java