001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2001-2005 Julian Hyde 008// Copyright (C) 2005-2012 Pentaho and others 009// All Rights Reserved. 010*/ 011package mondrian.rolap; 012 013import mondrian.olap.*; 014import mondrian.rolap.TupleReader.MemberBuilder; 015import mondrian.rolap.sql.MemberChildrenConstraint; 016import mondrian.rolap.sql.TupleConstraint; 017 018import java.util.*; 019 020/** 021 * <code>CacheMemberReader</code> implements {@link MemberReader} by reading 022 * from a pre-populated array of {@link mondrian.olap.Member}s. 023 * <p>Note: CacheMemberReader can not handle ragged hierarchies. (HR 024 * Tests fail if {@link SmartMemberReader} is replaced with 025 * CacheMemberReader). 026 * 027 * @author jhyde 028 * @since 21 December, 2001 029 */ 030class CacheMemberReader implements MemberReader, MemberCache { 031 private final MemberSource source; 032 private final List<RolapMember> members; 033 /** Maps a {@link MemberKey} to a {@link RolapMember}. */ 034 private final Map<Object, RolapMember> mapKeyToMember; 035 036 CacheMemberReader(MemberSource source) { 037 this.source = source; 038 if (false) { 039 // we don't want the reader to write back to our cache 040 Util.discard(source.setCache(this)); 041 } 042 this.mapKeyToMember = new HashMap<Object, RolapMember>(); 043 this.members = source.getMembers(); 044 for (int i = 0; i < members.size(); i++) { 045 RolapMember member = RolapUtil.strip(members.get(i)); 046 ((RolapMemberBase) member).setOrdinal(i); 047 } 048 } 049 050 // implement MemberReader 051 public RolapHierarchy getHierarchy() { 052 return source.getHierarchy(); 053 } 054 055 public boolean setCache(MemberCache cache) { 056 // we do not support cache writeback -- we must be masters of our 057 // own cache 058 return false; 059 } 060 061 public RolapMember substitute(RolapMember member) { 062 return member; 063 } 064 065 public RolapMember desubstitute(RolapMember member) { 066 return member; 067 } 068 069 public RolapMember getMemberByKey( 070 RolapLevel level, List<Comparable> keyValues) 071 { 072 assert keyValues.size() == 1; 073 return mapKeyToMember.get(keyValues.get(0)); 074 } 075 076 // implement MemberReader 077 public List<RolapMember> getMembers() { 078 return members; 079 } 080 081 // implement MemberCache 082 public Object makeKey(RolapMember parent, Object key) { 083 return new MemberKey(parent, key); 084 } 085 086 // implement MemberCache 087 public RolapMember getMember(Object key) { 088 return mapKeyToMember.get(key); 089 } 090 public RolapMember getMember(Object key, boolean mustCheckCacheStatus) { 091 return mapKeyToMember.get(key); 092 } 093 094 // implement MemberCache 095 public Object putMember(Object key, RolapMember value) { 096 return mapKeyToMember.put(key, value); 097 } 098 099 // don't need to implement this MemberCache method because we're never 100 // used in a context where it is needed 101 public void putChildren( 102 RolapMember member, 103 MemberChildrenConstraint constraint, 104 List<RolapMember> children) 105 { 106 throw new UnsupportedOperationException(); 107 } 108 109 // don't need to implement this MemberCache method because we're never 110 // used in a context where it is needed 111 public void putChildren( 112 RolapLevel level, 113 TupleConstraint constraint, 114 List<RolapMember> children) 115 { 116 throw new UnsupportedOperationException(); 117 } 118 119 // this cache is immutable 120 public boolean isMutable() 121 { 122 return false; 123 } 124 125 public RolapMember removeMember(Object key) 126 { 127 throw new UnsupportedOperationException(); 128 } 129 130 public RolapMember removeMemberAndDescendants(Object key) 131 { 132 throw new UnsupportedOperationException(); 133 } 134 135 // don't need to implement this MemberCache method because we're never 136 // used in a context where it is needed 137 public List<RolapMember> getChildrenFromCache( 138 RolapMember member, 139 MemberChildrenConstraint constraint) 140 { 141 return null; 142 } 143 144 // don't need to implement this MemberCache method because we're never 145 // used in a context where it is needed 146 public List<RolapMember> getLevelMembersFromCache( 147 RolapLevel level, 148 TupleConstraint constraint) 149 { 150 return null; 151 } 152 153 public RolapMember lookupMember( 154 List<Id.Segment> uniqueNameParts, 155 boolean failIfNotFound) 156 { 157 return RolapUtil.lookupMember(this, uniqueNameParts, failIfNotFound); 158 } 159 160 public List<RolapMember> getRootMembers() { 161 List<RolapMember> list = new ArrayList<RolapMember>(); 162 for (RolapMember member : members) { 163 if (member.getParentMember() == null) { 164 list.add(member); 165 } 166 } 167 return list; 168 } 169 170 public List<RolapMember> getMembersInLevel( 171 RolapLevel level) 172 { 173 List<RolapMember> list = new ArrayList<RolapMember>(); 174 int levelDepth = level.getDepth(); 175 for (RolapMember member : members) { 176 if (member.getLevel().getDepth() == levelDepth) { 177 list.add(member); 178 } 179 } 180 return list; 181 } 182 183 public List<RolapMember> getMembersInLevel( 184 RolapLevel level, 185 TupleConstraint constraint) 186 { 187 return getMembersInLevel(level); 188 } 189 190 public int getLevelMemberCount(RolapLevel level) { 191 int count = 0; 192 int levelDepth = level.getDepth(); 193 for (Member member : members) { 194 if (member.getLevel().getDepth() == levelDepth) { 195 ++count; 196 } 197 } 198 return count; 199 } 200 201 public void getMemberChildren( 202 RolapMember parentMember, 203 List<RolapMember> children) 204 { 205 for (Member member : members) { 206 if (member.getParentMember() == parentMember) { 207 ((List)children).add(member); 208 } 209 } 210 } 211 212 public Map<? extends Member, Access> getMemberChildren( 213 RolapMember member, 214 List<RolapMember> children, 215 MemberChildrenConstraint constraint) 216 { 217 getMemberChildren(member, children); 218 return Util.toNullValuesMap(children); 219 } 220 221 public void getMemberChildren( 222 List<RolapMember> parentMembers, 223 List<RolapMember> children) 224 { 225 for (Member member : members) { 226 if (parentMembers.contains(member.getParentMember())) { 227 ((List)children).add(member); 228 } 229 } 230 } 231 232 public Map<? extends Member, Access> getMemberChildren( 233 List<RolapMember> parentMembers, 234 List<RolapMember> children, 235 MemberChildrenConstraint constraint) 236 { 237 getMemberChildren(parentMembers, children); 238 return Util.toNullValuesMap(children); 239 } 240 241 public RolapMember getLeadMember(RolapMember member, int n) { 242 if (n >= 0) { 243 for (int ordinal = member.getOrdinal(); ordinal < members.size(); 244 ordinal++) 245 { 246 if ((members.get(ordinal).getLevel() == member.getLevel()) 247 && (n-- == 0)) 248 { 249 return members.get(ordinal); 250 } 251 } 252 return (RolapMember) member.getHierarchy().getNullMember(); 253 254 } else { 255 for (int ordinal = member.getOrdinal(); ordinal >= 0; ordinal--) { 256 if ((members.get(ordinal).getLevel() == member.getLevel()) 257 && (n++ == 0)) 258 { 259 return members.get(ordinal); 260 } 261 } 262 return (RolapMember) member.getHierarchy().getNullMember(); 263 } 264 } 265 266 public void getMemberRange( 267 RolapLevel level, 268 RolapMember startMember, 269 RolapMember endMember, 270 List<RolapMember> list) 271 { 272 assert startMember != null; 273 assert endMember != null; 274 assert startMember.getLevel() == endMember.getLevel(); 275 final int endOrdinal = endMember.getOrdinal(); 276 for (int i = startMember.getOrdinal(); i <= endOrdinal; i++) { 277 if (members.get(i).getLevel() == endMember.getLevel()) { 278 list.add(members.get(i)); 279 } 280 } 281 } 282 283 public int getMemberCount() { 284 return members.size(); 285 } 286 287 public int compare( 288 RolapMember m1, 289 RolapMember m2, 290 boolean siblingsAreEqual) 291 { 292 if (m1 == m2) { 293 return 0; 294 } 295 if (siblingsAreEqual 296 && (m1.getParentMember() == m2.getParentMember())) 297 { 298 return 0; 299 } 300 Util.assertTrue(members.get(m1.getOrdinal()) == m1); 301 Util.assertTrue(members.get(m2.getOrdinal()) == m2); 302 303 return (m1.getOrdinal() < m2.getOrdinal()) ? -1 : 1; 304 } 305 306 public MemberBuilder getMemberBuilder() { 307 return null; 308 } 309 310 public RolapMember getDefaultMember() { 311 RolapMember defaultMember = 312 (RolapMember) getHierarchy().getDefaultMember(); 313 if (defaultMember != null) { 314 return defaultMember; 315 } 316 return getRootMembers().get(0); 317 } 318 319 public RolapMember getMemberParent(RolapMember member) { 320 return member.getParentMember(); 321 } 322} 323 324// End CacheMemberReader.java