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-2007 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-release/3.0/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 public RolapMember getLeadMember(RolapMember member, int n) {
064 return substitute(
065 memberReader.getLeadMember(desubstitute(member), n));
066 }
067
068 public List<RolapMember> getMembersInLevel(
069 RolapLevel level,
070 int startOrdinal,
071 int endOrdinal)
072 {
073 return substitute(
074 memberReader.getMembersInLevel(level, startOrdinal, endOrdinal));
075 }
076
077 public void getMemberRange(
078 RolapLevel level,
079 RolapMember startMember,
080 RolapMember endMember,
081 List<RolapMember> list)
082 {
083 memberReader.getMemberRange(
084 level,
085 desubstitute(startMember),
086 desubstitute(endMember),
087 new SubstitutingMemberList(list));
088 }
089
090 public int compare(
091 RolapMember m1,
092 RolapMember m2,
093 boolean siblingsAreEqual)
094 {
095 return memberReader.compare(
096 desubstitute(m1),
097 desubstitute(m2),
098 siblingsAreEqual);
099 }
100
101 public RolapHierarchy getHierarchy() {
102 return memberReader.getHierarchy();
103 }
104
105 public boolean setCache(MemberCache cache) {
106 // cache semantics don't make sense if members are not comparable
107 throw new UnsupportedOperationException();
108 }
109
110 public RolapMember[] getMembers() {
111 // might make sense, but I doubt it
112 throw new UnsupportedOperationException();
113 }
114
115 public List<RolapMember> getRootMembers() {
116 return substitute(memberReader.getRootMembers());
117 }
118
119 public void getMemberChildren(
120 RolapMember parentMember,
121 List<RolapMember> children)
122 {
123 memberReader.getMemberChildren(
124 desubstitute(parentMember),
125 new SubstitutingMemberList(children));
126 }
127
128 public void getMemberChildren(
129 List<RolapMember> parentMembers,
130 List<RolapMember> children)
131 {
132 memberReader.getMemberChildren(
133 desubstitute(parentMembers),
134 new SubstitutingMemberList(children));
135 }
136
137 public int getMemberCount() {
138 return memberReader.getMemberCount();
139 }
140
141 public RolapMember lookupMember(
142 List<Id.Segment> uniqueNameParts,
143 boolean failIfNotFound)
144 {
145 return substitute(
146 memberReader.lookupMember(uniqueNameParts, failIfNotFound));
147 }
148
149 public void getMemberChildren(
150 RolapMember member,
151 List<RolapMember> children,
152 MemberChildrenConstraint constraint)
153 {
154 memberReader.getMemberChildren(
155 desubstitute(member),
156 new SubstitutingMemberList(children),
157 constraint);
158 }
159
160 public void getMemberChildren(
161 List<RolapMember> parentMembers,
162 List<RolapMember> children,
163 MemberChildrenConstraint constraint)
164 {
165 memberReader.getMemberChildren(
166 substitute(parentMembers),
167 new SubstitutingMemberList(children),
168 constraint);
169 }
170
171 public List<RolapMember> getMembersInLevel(
172 RolapLevel level,
173 int startOrdinal,
174 int endOrdinal,
175 TupleConstraint constraint)
176 {
177 return substitute(
178 memberReader.getMembersInLevel(
179 level, startOrdinal, endOrdinal, constraint));
180 }
181
182 public RolapMember getDefaultMember() {
183 return substitute(memberReader.getDefaultMember());
184 }
185
186 public RolapMember getMemberParent(RolapMember member) {
187 return substitute(memberReader.getMemberParent(desubstitute(member)));
188 }
189
190 public TupleReader.MemberBuilder getMemberBuilder() {
191 return memberBuilder;
192 }
193
194 /**
195 * List which writes through to an underlying list, substituting members
196 * as they are written and desubstituting as they are read.
197 */
198 private class SubstitutingMemberList extends AbstractList<RolapMember> {
199 private final List<RolapMember> list;
200
201 SubstitutingMemberList(List<RolapMember> list) {
202 this.list = list;
203 }
204
205 public RolapMember get(int index) {
206 return desubstitute(list.get(index));
207 }
208
209 public int size() {
210 return list.size();
211 }
212
213 public RolapMember set(int index, RolapMember element) {
214 return desubstitute(list.set(index, substitute(element)));
215 }
216
217 public void add(int index, RolapMember element) {
218 list.add(index, substitute(element));
219 }
220
221 public RolapMember remove(int index) {
222 return list.remove(index);
223 }
224 }
225
226 private class SubstitutingMemberBuilder
227 implements TupleReader.MemberBuilder
228 {
229 public MemberCache getMemberCache() {
230 return memberReader.getMemberBuilder().getMemberCache();
231 }
232
233 public Object getMemberCacheLock() {
234 return memberReader.getMemberBuilder().getMemberCacheLock();
235 }
236
237 public RolapMember makeMember(
238 RolapMember parentMember,
239 RolapLevel childLevel,
240 Object value,
241 Object captionValue,
242 boolean parentChild,
243 ResultSet resultSet,
244 Object key,
245 int column) throws SQLException
246 {
247 return substitute(
248 memberReader.getMemberBuilder().makeMember(
249 desubstitute(parentMember),
250 childLevel,
251 value,
252 captionValue,
253 parentChild,
254 resultSet,
255 key,
256 column));
257 }
258 }
259 }
260
261 // End SubstitutingMemberReader.java