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) 2007-2012 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.rolap; 011 012import mondrian.olap.Access; 013import mondrian.olap.Id; 014import mondrian.olap.Member; 015import mondrian.rolap.sql.MemberChildrenConstraint; 016import mondrian.rolap.sql.TupleConstraint; 017 018import java.sql.SQLException; 019import java.util.*; 020 021/** 022 * Implementation of {@link MemberReader} which replaces given members 023 * with a substitute. 024 * 025 * <p>Derived classes must implement the {@link #substitute(RolapMember)} and 026 * {@link #desubstitute(RolapMember)} methods. 027 * 028 * @author jhyde 029 * @since Oct 5, 2007 030 */ 031public abstract class SubstitutingMemberReader extends DelegatingMemberReader { 032 private final TupleReader.MemberBuilder memberBuilder = 033 new SubstitutingMemberBuilder(); 034 035 /** 036 * Creates a SubstitutingMemberReader. 037 * 038 * @param memberReader Parent member reader 039 */ 040 SubstitutingMemberReader(MemberReader memberReader) { 041 super(memberReader); 042 } 043 044 // Helper methods 045 046 private List<RolapMember> desubstitute(List<RolapMember> members) { 047 List<RolapMember> list = new ArrayList<RolapMember>(members.size()); 048 for (RolapMember member : members) { 049 list.add(desubstitute(member)); 050 } 051 return list; 052 } 053 054 private List<RolapMember> substitute(List<RolapMember> members) { 055 List<RolapMember> list = new ArrayList<RolapMember>(members.size()); 056 for (RolapMember member : members) { 057 list.add(substitute(member)); 058 } 059 return list; 060 } 061 062 // ~ -- Implementations of MemberReader methods --------------------------- 063 064 @Override 065 public RolapMember getLeadMember(RolapMember member, int n) { 066 return substitute( 067 memberReader.getLeadMember(desubstitute(member), n)); 068 } 069 070 @Override 071 public List<RolapMember> getMembersInLevel( 072 RolapLevel level) 073 { 074 return substitute(memberReader.getMembersInLevel(level)); 075 } 076 077 @Override 078 public void getMemberRange( 079 RolapLevel level, 080 RolapMember startMember, 081 RolapMember endMember, 082 List<RolapMember> list) 083 { 084 memberReader.getMemberRange( 085 level, 086 desubstitute(startMember), 087 desubstitute(endMember), 088 new SubstitutingMemberList(list)); 089 } 090 091 @Override 092 public int compare( 093 RolapMember m1, 094 RolapMember m2, 095 boolean siblingsAreEqual) 096 { 097 return memberReader.compare( 098 desubstitute(m1), 099 desubstitute(m2), 100 siblingsAreEqual); 101 } 102 103 @Override 104 public RolapHierarchy getHierarchy() { 105 return memberReader.getHierarchy(); 106 } 107 108 @Override 109 public boolean setCache(MemberCache cache) { 110 // cache semantics don't make sense if members are not comparable 111 throw new UnsupportedOperationException(); 112 } 113 114 @Override 115 public List<RolapMember> getMembers() { 116 // might make sense, but I doubt it 117 throw new UnsupportedOperationException(); 118 } 119 120 @Override 121 public List<RolapMember> getRootMembers() { 122 return substitute(memberReader.getRootMembers()); 123 } 124 125 @Override 126 public void getMemberChildren( 127 RolapMember parentMember, 128 List<RolapMember> children) 129 { 130 memberReader.getMemberChildren( 131 desubstitute(parentMember), 132 new SubstitutingMemberList(children)); 133 } 134 135 @Override 136 public void getMemberChildren( 137 List<RolapMember> parentMembers, 138 List<RolapMember> children) 139 { 140 memberReader.getMemberChildren( 141 desubstitute(parentMembers), 142 new SubstitutingMemberList(children)); 143 } 144 145 @Override 146 public int getMemberCount() { 147 return memberReader.getMemberCount(); 148 } 149 150 @Override 151 public RolapMember lookupMember( 152 List<Id.Segment> uniqueNameParts, 153 boolean failIfNotFound) 154 { 155 return substitute( 156 memberReader.lookupMember(uniqueNameParts, failIfNotFound)); 157 } 158 159 public Map<? extends Member, Access> getMemberChildren( 160 RolapMember member, 161 List<RolapMember> children, 162 MemberChildrenConstraint constraint) 163 { 164 return memberReader.getMemberChildren( 165 desubstitute(member), 166 new SubstitutingMemberList(children), 167 constraint); 168 } 169 170 public Map<? extends Member, Access> getMemberChildren( 171 List<RolapMember> parentMembers, 172 List<RolapMember> children, 173 MemberChildrenConstraint constraint) 174 { 175 return memberReader.getMemberChildren( 176 desubstitute(parentMembers), 177 new SubstitutingMemberList(children), 178 constraint); 179 } 180 181 @Override 182 public List<RolapMember> getMembersInLevel( 183 RolapLevel level, TupleConstraint constraint) 184 { 185 return substitute( 186 memberReader.getMembersInLevel( 187 level, constraint)); 188 } 189 190 @Override 191 public RolapMember getDefaultMember() { 192 return substitute(memberReader.getDefaultMember()); 193 } 194 195 @Override 196 public RolapMember getMemberParent(RolapMember member) { 197 return substitute(memberReader.getMemberParent(desubstitute(member))); 198 } 199 200 @Override 201 public TupleReader.MemberBuilder getMemberBuilder() { 202 return memberBuilder; 203 } 204 205 /** 206 * List which writes through to an underlying list, substituting members 207 * as they are written and desubstituting as they are read. 208 */ 209 class SubstitutingMemberList extends AbstractList<RolapMember> { 210 private final List<RolapMember> list; 211 212 SubstitutingMemberList(List<RolapMember> list) { 213 this.list = list; 214 } 215 216 @Override 217 public RolapMember get(int index) { 218 return desubstitute(list.get(index)); 219 } 220 221 @Override 222 public int size() { 223 return list.size(); 224 } 225 226 @Override 227 public RolapMember set(int index, RolapMember element) { 228 return desubstitute(list.set(index, substitute(element))); 229 } 230 231 @Override 232 public void add(int index, RolapMember element) { 233 list.add(index, substitute(element)); 234 } 235 236 @Override 237 public RolapMember remove(int index) { 238 return list.remove(index); 239 } 240 } 241 242 private class SubstitutingMemberBuilder 243 implements TupleReader.MemberBuilder 244 { 245 public MemberCache getMemberCache() { 246 return memberReader.getMemberBuilder().getMemberCache(); 247 } 248 249 public Object getMemberCacheLock() { 250 return memberReader.getMemberBuilder().getMemberCacheLock(); 251 } 252 253 public RolapMember makeMember( 254 RolapMember parentMember, 255 RolapLevel childLevel, 256 Object value, 257 Object captionValue, 258 boolean parentChild, 259 SqlStatement stmt, 260 Object key, 261 int column) throws SQLException 262 { 263 return substitute( 264 memberReader.getMemberBuilder().makeMember( 265 desubstitute(parentMember), 266 childLevel, 267 value, 268 captionValue, 269 parentChild, 270 stmt, 271 key, 272 column)); 273 } 274 275 public RolapMember allMember() { 276 return substitute(memberReader.getHierarchy().getAllMember()); 277 } 278 } 279} 280 281// End SubstitutingMemberReader.java