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