001 /*
002 // $Id: //open/mondrian-release/3.0/src/main/mondrian/rolap/SmartMemberListCache.java#2 $
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-release/3.0/src/main/mondrian/rolap/SmartMemberListCache.java#2 $
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